#include "TCPServer.hpp"
#include "Calculator.hpp"
#include "Protocol.hpp"
#include "Common.hpp"
#include "Daemon.hpp"

using cal_func = function<Response(const Request&)>;

class Parse
{
public:
    Parse(cal_func cal)
        :_cal(cal)
    {}
    // package 不一定会是一个完整的报文，所以要先检查 Decode
    // 不完整 -> 继续读
    // 完整 -> 解码获取报文 -> 反序列化 -> 计算 -> 计算完成后的结果还需要发送回去，所以还需要进行序列化并添加报头 Encode
    string Entry(string& package)
    {
        string message;
        string respstr;
        while(Decode(package, &message))
        {
            // 1. 判断报文是否完整
            if(message.empty()) break;  // 如果报文不完整，返回空串
            // 此时message就是报文
            // 2. 反序列化成结构体,message是一个曾经被序列化的字符串
            Request req;
            if(!req.deserialization(message)) break;
            // 此时req就是要计算的数据
            // 3. 计算
            Response resp = _cal(req);
            // resp 是计算后的答案结构体
            // 4. 答案序列化
            string ans;
            if(!resp.Serialization(ans)) break;
            // 5. 添加报头 Encode
            if(!Encode(ans)) break;
            // 拼接
            respstr += ans;
        }
        return respstr;
    }
private:
    cal_func _cal;
};

int main()
{
    ENABLE_FILE_LOG();
    Daemon(false,false);
    // 计算模块
    Calculate mycal;
    // 解析模块
    Parse p([&mycal](const Request& req){ return mycal.Execute(req); });
    // 通信模块
    unique_ptr<TcpServer> tsvr = make_unique<TcpServer>([&p](string& package){ return p.Entry(package); });
    tsvr->InitServer();
    tsvr->Start();

    return 0;
}